gtkimcontextwayland: Convert byte based offset to char based offset in delete_surroun...
authorAlynx Zhou <alynx.zhou@gmail.com>
Thu, 24 Nov 2022 10:35:47 +0000 (18:35 +0800)
committerAlynx Zhou <alynx.zhou@gmail.com>
Tue, 20 Dec 2022 01:46:52 +0000 (09:46 +0800)
ClutterInputFocus/GtkIMContext uses char based offset for
delete_surrounding, however, text_input_v3 uses byte based offset for
it. Currently only GTK with mutter can work correctly via text_input_v3
because they both forget to convert between char based offset and byte
based offset.

This commit fixes it in GTK by converting byte based offset to char
based offset with the UTF-8 encoded surrounding text.

Fixes <https://gitlab.gnome.org/GNOME/gtk/-/issues/4566>.

modules/input/imwayland.c

index fb3e1e399686892c4d32490ce9ffdd28d444e3a1..1fc7ab671d1fe6c55d089facd0ccb33bc805aab4 100644 (file)
@@ -237,14 +237,24 @@ text_input_delete_surrounding_text (void                     *data,
 {
   GtkIMContextWaylandGlobal *global = data;
   GtkIMContextWayland *context;
+  char *cursor_pointer;
+  uint32_t char_before_length;
+  uint32_t char_after_length;
 
   if (!global->current)
       return;
   
   context = GTK_IM_CONTEXT_WAYLAND (global->current);
 
-  context->pending_surrounding_delete.before_length = before_length;
-  context->pending_surrounding_delete.after_length = after_length;
+  /* We already got byte lengths from text_input_v3, but GTK uses char lengths
+   * for delete_surrounding, So convert it here.
+   */
+  cursor_pointer = context->surrounding.text + context->surrounding.cursor_idx;
+  char_before_length = g_utf8_pointer_to_offset (cursor_pointer - before_length, cursor_pointer);
+  char_after_length = g_utf8_pointer_to_offset (cursor_pointer, cursor_pointer + after_length);
+
+  context->pending_surrounding_delete.before_length = char_before_length;
+  context->pending_surrounding_delete.after_length = char_after_length;
 }
 
 static void